package com.bluetrum.abmate.multipoint;

import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;

import android.os.Bundle;
import android.view.View;
import android.widget.PopupMenu;
import android.widget.Toast;

import com.bluetrum.abmate.R;
import com.bluetrum.abmate.cmd.SimpleRequestCallback2;
import com.bluetrum.abmate.databinding.ActivityMultipointBinding;
import com.bluetrum.abmate.utils.Utils;
import com.bluetrum.abmate.viewmodels.SharedViewModel;
import com.bluetrum.devicemanager.cmd.Request;
import com.bluetrum.devicemanager.cmd.request.MultipointRequest;
import com.bluetrum.devicemanager.models.Multipoint;
import com.bluetrum.devicemanager.models.SinglePoint;

import java.util.List;
import java.util.stream.Collectors;

import dagger.hilt.android.AndroidEntryPoint;

@AndroidEntryPoint
public class MultipointActivity extends AppCompatActivity
        implements EndpointAdapter.OnItemClickListener {

    private SharedViewModel mViewModel;

    private ActivityMultipointBinding binding;
    private EndpointAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        binding = ActivityMultipointBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setTitle(R.string.function_multipoint);

        setupListView();
        setupObservers();

        binding.enableSwitch.setOnClickListener(this::clickSwitch);
    }

    private void setupListView() {
        RecyclerView recyclerView = binding.recyclerView;

        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        final DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
        recyclerView.addItemDecoration(dividerItemDecoration);

        final SimpleItemAnimator itemAnimator = (SimpleItemAnimator) recyclerView.getItemAnimator();
        if (itemAnimator != null) itemAnimator.setSupportsChangeAnimations(false);

        adapter = new EndpointAdapter();
        adapter.setLocalBluetoothName(mViewModel.getLocalBluetoothName());
        adapter.setOnItemClickListener(this);
        recyclerView.setAdapter(adapter);
    }

    private void setupObservers() {
        mViewModel.getDeviceMultipointStatus().observe(this, status -> {
            binding.enableSwitch.setChecked(Boolean.TRUE.equals(status));
        });
        getDeviceMultipointInfo().observe(this, multipoint -> {
            if (multipoint != null) {
                adapter.updateList(multipoint);
            }
        });
    }

    @NonNull
    private LiveData<Multipoint> getDeviceMultipointInfo() {
        LiveData<Multipoint> multipointLiveData = mViewModel.getDeviceMultipointInfo();

        // 如果保存的本地地址为空，则使用MediatorLiveData监控连接的设备，设备数量为1的时候就是本机
        final String localBluetoothAddress = Utils.getPrefsLocalBluetoothAddress(this);

        if (localBluetoothAddress == null) {
            MediatorLiveData<Multipoint> mediatorLiveData = new MediatorLiveData<>();
            mediatorLiveData.addSource(multipointLiveData, multipoint -> {
                if (multipoint != null) {
                    List<SinglePoint> endpoints = multipoint.getEndpoints();
                    final String bluetoothAddress = Utils.getPrefsLocalBluetoothAddress(this);
                    // 如果设备数量为1，且目前没有保存本机蓝牙地址，保存下来
                    if (endpoints.size() == 1 && bluetoothAddress == null) {
                        SinglePoint endpoint = endpoints.get(0);
                        String address = endpoint.getAddress();
                        Utils.setPrefsLocalBluetoothAddress(this, address);
                        // 更新Adapter
                        adapter.setLocalBluetoothAddress(address);
                    }
                }
                mediatorLiveData.postValue(multipoint);
            });
            return mediatorLiveData;
        } else {
            adapter.setLocalBluetoothAddress(localBluetoothAddress);
            return multipointLiveData;
        }
    }

    private void clickSwitch(View view) {
        boolean enable = binding.enableSwitch.isChecked();
        Multipoint multipoint = mViewModel.getDeviceMultipointInfo().getValue();

        Request request;
        // 如果是关闭，且连接不止一台设备，则需要同时下发断开另外设备的命令
        // 目前只处理双设备连接
        if (!enable && multipoint != null && multipoint.getEndpoints().size() > 1) {
            List<SinglePoint> endpoints = multipoint.getEndpoints();

            // 过滤掉本机地址
            final String localBluetoothAddress = Utils.getPrefsLocalBluetoothAddress(this);
            if (localBluetoothAddress != null) {
                List<SinglePoint> filteredEndpoints = endpoints.stream()
                        .filter(endpoint -> !endpoint.getAddress().equalsIgnoreCase(localBluetoothAddress))
                        .collect(Collectors.toList());
                // 取最后一个断开
                SinglePoint endpoint = filteredEndpoints.get(filteredEndpoints.size() - 1);
                request = MultipointRequest.disableRequest(endpoint.getAddressBytes());
            } else {
                // 过滤掉本机名称
                String localBluetoothName = mViewModel.getLocalBluetoothName();
                if (localBluetoothName != null && !localBluetoothName.isEmpty()) {
                    List<SinglePoint> filteredEndpoints = multipoint.getEndpoints().stream()
                            .filter(endpoint -> !endpoint.getBluetoothName().equalsIgnoreCase(localBluetoothName))
                            .collect(Collectors.toList());
                    // 取最后一个断开
                    SinglePoint endpoint = filteredEndpoints.get(filteredEndpoints.size() - 1);
                    request = MultipointRequest.disableRequest(endpoint.getAddressBytes());
                } else {
                    // 取最后一个断开
                    SinglePoint endpoint = endpoints.get(endpoints.size() - 1);
                    request = MultipointRequest.disableRequest(endpoint.getAddressBytes());
                }
            }
        } else {
            request = MultipointRequest.enableRequest(enable);
        }

        mViewModel.sendRequest(request, new SimpleRequestCallback2() {
            @Override
            public void onComplete(boolean result) {
                @StringRes int msgId = result ? R.string.request_succeeded : R.string.request_failed;
                Toast.makeText(MultipointActivity.this, msgId, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onTimeout() {
                Toast.makeText(MultipointActivity.this, R.string.request_timeout, Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onItemClick(final View view, final SinglePoint endpoint) {
        // 弹出操作菜单
        android.widget.PopupMenu popup = new PopupMenu(this, view);
        popup.inflate(R.menu.menu_multipoint_action);
        popup.setOnMenuItemClickListener(item -> {
            int itemId = item.getItemId();
            if (itemId == R.id.connect) {
                mViewModel.sendRequest(MultipointRequest.connectRequest(endpoint.getAddressBytes()));
                return true;
            } else if (itemId == R.id.disconnect) {
                mViewModel.sendRequest(MultipointRequest.disconnectRequest(endpoint.getAddressBytes()));
                return true;
            } else if (itemId == R.id.unpair) {
                mViewModel.sendRequest(MultipointRequest.unpairRequest(endpoint.getAddressBytes()));
                return true;
            }
            return false;
        });
        if (endpoint.isConnected()) {
            popup.getMenu().findItem(R.id.connect).setVisible(false);
        } else {
            popup.getMenu().findItem(R.id.disconnect).setVisible(false);
        }
        popup.show();
    }
}